Skip to content

Add @react-grab/paper package for Paper clipboard paste#211

Open
aidenybai wants to merge 5 commits intomainfrom
aiden/paper-clipboard-paste
Open

Add @react-grab/paper package for Paper clipboard paste#211
aidenybai wants to merge 5 commits intomainfrom
aiden/paper-clipboard-paste

Conversation

@aidenybai
Copy link
Owner

@aidenybai aidenybai commented Mar 4, 2026

Converts DOM elements to Paper's native clipboard paste format (paper-paste-start embed). Supports colors (lab/oklab/oklch/srgb → OKLCH), native SVG nodes with fill+stroke, React component names via bippy, text with font/color/size, backgrounds, borders, shadows, gradients, multi-element selection, and getBoundingClientRect sizing.

Made-with: Cursor


Note

Medium Risk
Introduces a large new DOM/CSS-to-clipboard conversion path and changes clipboard HTML payload generation, which could cause unexpected paste behavior or runtime issues across browsers/sites.

Overview
Adds a new workspace package @react-grab/paper that converts DOM nodes into Paper’s native clipboard embed (paper-paste-start), including style/geometry extraction and SVG handling, plus small test artifacts (test-paste.html, sample clipboard HTML).

Integrates Paper output into react-grab’s copy pipeline by generating paperHtml (with React component-based layer naming via bippy) and embedding it into the text/html clipboard payload while keeping the existing plain-text/HTML fallback behavior. Updates monorepo build/dev filters and bundling (tsup noExternal) to include the new package and adds it as a dependency of react-grab.

Written by Cursor Bugbot for commit 4cd1f98. This will update automatically on new commits. Configure here.


Summary by cubic

Adds a new @react-grab/paper package and hooks it into the copy flow to generate Paper clipboard embeds from selected DOM. Also fixes Vercel builds by simplifying the Paper build and removing stray debug files.

  • New Features

    • Converts DOM to Paper embed (paper-paste-start) with multi-select and absolute positioning.
    • Preserves text styles (font, size, weight, italic, line height, letter spacing, wrapping) and box styles (backgrounds, borders, radius, shadows, gaps).
    • Normalizes colors (lab/oklab/oklch/srgb → OKLCH) and parses linear-gradients.
    • Adds native SVG support (root and shapes) with fill/stroke, viewBox, groups, opacity.
    • Labels layers via React component names; clipboard carries Paper HTML with plaintext fallback. Exposes copyDomToPaper and a test page.
  • Dependencies

    • Adds workspace package @react-grab/paper (built with tsup) and includes it in Turbo build/dev filters.
    • Updates react-grab to depend on and bundle @react-grab/paper via tsup noExternal to avoid build-order issues.
    • Fixes Vercel build by removing non-cross-platform scripts, deleting debug files, and updating website script.js.

Written for commit 4cd1f98. Summary will update on new commits.

Converts DOM elements to Paper's native clipboard paste format
(paper-paste-start embed). Supports colors (lab/oklab/oklch/srgb →
OKLCH), native SVG nodes with fill+stroke, React component names via
bippy, text with font/color/size, backgrounds, borders, shadows,
gradients, multi-element selection, and getBoundingClientRect sizing.

Made-with: Cursor
@pullfrog
Copy link
Contributor

pullfrog bot commented Mar 4, 2026

This run croaked 😵

The workflow encountered an error before any progress could be reported. Please check the link below for details.

Pullfrog  | Rerun failed job ➔View workflow run | Triggered by Pullfrogpullfrog.com𝕏

@vercel
Copy link
Contributor

vercel bot commented Mar 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-grab-website Error Error Mar 5, 2026 5:44am

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 4, 2026

Open in StackBlitz

@react-grab/cli

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/cli@211

grab

npm i https://pkg.pr.new/aidenybai/react-grab/grab@211

@react-grab/ami

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/ami@211

@react-grab/amp

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/amp@211

@react-grab/claude-code

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/claude-code@211

@react-grab/codex

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/codex@211

@react-grab/copilot

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/copilot@211

@react-grab/cursor

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/cursor@211

@react-grab/droid

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/droid@211

@react-grab/gemini

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/gemini@211

@react-grab/opencode

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/opencode@211

react-grab

npm i https://pkg.pr.new/aidenybai/react-grab@211

@react-grab/relay

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/relay@211

@react-grab/utils

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/utils@211

commit: 4cd1f98

Fixes Vercel build failure where tsup tried to resolve
@react-grab/paper/dist before the workspace dep was built.

Made-with: Cursor
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 11 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/paper/src/constants.ts">

<violation number="1" location="packages/paper/src/constants.ts:57">
P2: Regex matches unintended class names due to missing word boundaries</violation>
</file>

<file name="packages/paper/package.json">

<violation number="1" location="packages/paper/package.json:11">
P2: Dual package type exports lack explicit `.d.cts` for CommonJS, which causes TypeScript errors under `Node16` module resolution.</violation>

<violation number="2" location="packages/paper/package.json:18">
P2: The `rm -rf dist` command is not cross-platform and is redundant since `tsup` is already configured to clean the output directory.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

export const UNIQUE_ID_LENGTH = 26;

export const UTILITY_CLASS_PATTERN =
/^(flex|grid|p[xytrbl]?-|m[xytrbl]?-|w-|h-|bg-|text-|border-|rounded|shadow|opacity-|gap-|space-|font-|leading-|tracking-|overflow-|z-|relative|absolute|fixed|sticky|hidden|block|inline|sr-only|col-|row-|items-|justify-|self-|order-|grow|shrink|basis-)/;
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Regex matches unintended class names due to missing word boundaries

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/paper/src/constants.ts, line 57:

<comment>Regex matches unintended class names due to missing word boundaries</comment>

<file context>
@@ -0,0 +1,57 @@
+export const UNIQUE_ID_LENGTH = 26;
+
+export const UTILITY_CLASS_PATTERN =
+  /^(flex|grid|p[xytrbl]?-|m[xytrbl]?-|w-|h-|bg-|text-|border-|rounded|shadow|opacity-|gap-|space-|font-|leading-|tracking-|overflow-|z-|relative|absolute|fixed|sticky|hidden|block|inline|sr-only|col-|row-|items-|justify-|self-|order-|grow|shrink|basis-)/;
</file context>
Fix with Cubic

],
"exports": {
".": {
"types": "./dist/index.d.ts",
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Dual package type exports lack explicit .d.cts for CommonJS, which causes TypeScript errors under Node16 module resolution.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/paper/package.json, line 11:

<comment>Dual package type exports lack explicit `.d.cts` for CommonJS, which causes TypeScript errors under `Node16` module resolution.</comment>

<file context>
@@ -0,0 +1,23 @@
+  ],
+  "exports": {
+    ".": {
+      "types": "./dist/index.d.ts",
+      "import": "./dist/index.js",
+      "require": "./dist/index.cjs"
</file context>
Fix with Cubic

): Promise<string> => {
const { domToPaper } = await import("./dom-to-paper");
const html = domToPaper(nodeOrNodes, options);
await navigator.clipboard.writeText(html);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copyDomToPaper writes HTML as plain text MIME

High Severity

copyDomToPaper calls navigator.clipboard.writeText(html) which writes the Paper embed HTML to the clipboard as text/plain. Paper reads paste data from the text/html MIME type (as seen in copy-content.ts line 177 using clipboardData.setData("text/html", ...)). This means the standalone copyDomToPaper function will never produce a paste that Paper can recognize. It needs to use navigator.clipboard.write() with a ClipboardItem containing a text/html blob.

Fix in Cursor Fix in Web

const color = cssColorToPaper(stopMatch[1]);
if (!color) continue;
stops.push({ position: stopMatch[2] ? parseFloat(stopMatch[2]) / 100 : -1, color, midpoint: 0.5 });
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gradient parser ignores non-rgb color stop formats

Medium Severity

The stopRegex in parseLinearGradient only matches rgb()/rgba() color stops, but the code's own comment (lines 115–116) acknowledges modern Chromium returns computed colors in lab()/oklch()/oklab() formats. When a computed backgroundImage contains gradient stops in these modern formats, the regex won't match any stops, stops.length < 2 triggers, and the entire gradient is silently dropped.

Fix in Cursor Fix in Web

@aidenybai
Copy link
Owner Author

@cursoragent vercel build failing

@cursor
Copy link

cursor bot commented Mar 5, 2026

I've fixed the Vercel build failure by addressing the following issues identified by the automated reviewers:

Changes Made

  1. Fixed non-cross-platform build command in @react-grab/paper:

    • Removed rm -rf dist && from the build script (tsup already has clean: true configured)
    • Removed NODE_ENV=production prefix (not needed as tsup handles production mode automatically)
    • Changed from: "build": "rm -rf dist && NODE_ENV=production tsup"
    • Changed to: "build": "tsup"
  2. Removed accidentally committed debugging files:

    • Deleted inspect-layout.js (Puppeteer debugging script)
    • Deleted inspect-page.html (layout inspection page)
  3. Verified all builds work correctly:

    • @react-grab/paper builds successfully
    • react-grab builds successfully
    • @react-grab/website builds successfully

Why This Fixes the Build

The rm -rf dist command doesn't work on all platforms (particularly Windows), and Vercel's build environment may have been encountering issues with the shell command. Since tsup already has clean: true configured in the config file, the manual deletion was redundant and potentially problematic.

The changes have been committed and pushed to the aiden/paper-clipboard-paste branch. The Vercel build should now succeed on the next deployment.

Open in Web Open in Cursor 

- Remove redundant 'rm -rf dist' and 'NODE_ENV=production' from @react-grab/paper build script (tsup already handles cleaning and production mode)
- Delete accidentally committed debugging files: inspect-layout.js and inspect-page.html
- Update built script.js after changes

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

}

const stops: PaperGradientStop[] = [];
const stopRegex = /(rgba?\([^)]+\))\s*([\d.]+%)?/g;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gradient stop regex ignores non-rgb color formats

Medium Severity

The stopRegex in parseLinearGradient only matches rgb()/rgba() color stops, but the code's own comment (lines 115–116) acknowledges that modern Chromium returns computed colors in oklch()/oklab()/lab() formats. If a gradient's computed value uses these non-rgb color formats, no stops are captured, stops.length < 2 triggers, and the gradient is silently dropped. The same issue exists in parseBoxShadows where its regex also only matches rgba?(). Both parsers are inconsistent with parseRgbColor, which handles all six color formats.

Additional Locations (1)

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants